package com.fjwt.gz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fjwt.gz.components.mq.model.ExportExcelMQ;
import com.fjwt.gz.components.mq.vender.IMQSender;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.security.GzUserDetails;
import com.fjwt.gz.db.dto.ActivityAwardDTO;
import com.fjwt.gz.db.entity.StatActe017NumEntity;
import com.fjwt.gz.db.vo.StatActe017MchVO;
import com.fjwt.gz.db.vo.StatActe017NumVO;
import com.fjwt.gz.db.vo.StatActe017RecordVO;
import com.fjwt.gz.service.activity.platform.acte017.ACTE017Service;
import com.fjwt.gz.service.mapper.StatActe017NumMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * ACTE017越减越便宜活动--入链渠道机构统计表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-07-24
 */
@Slf4j
@Service
public class StatActe017NumService extends ServiceImpl<StatActe017NumMapper, StatActe017NumEntity> {

    @Autowired
    private StatActe017NumMapper statActe017NumMapper;
    @Autowired
    private SysExportTaskService sysExportTaskService;
    @Autowired
    private IMQSender mqSender;
    @Autowired
    private ACTE017Service acte017Service;

    /**
     * 查询 越减越便宜 通报表（机构明细）
     * @param iPage
     * @param activityAwardDTO
     * @return
     */
    public IPage<StatActe017NumVO> getAgentDetail(IPage iPage, ActivityAwardDTO activityAwardDTO) {
        return this.statActe017NumMapper.getActAgentDetaiList(iPage, activityAwardDTO);
    }

    /**
     * 导出越减越便宜活动通报表（机构明细）
     *
     * @param activityAwardDTO
     */
    public void exportAgentDetail(ActivityAwardDTO activityAwardDTO) {
        String fileName = "越减越便宜机构明细表--截至" + DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN);
        // 添加导出任务记录
        this.sysExportTaskService.addExportTask(
                GzUserDetails.getCurrentUserDetails().getSysUser(),
                fileName,
                Constants.EXPORT_TASK_ENUM.REQUEST_CODE.AGENT_DETAIL,
                Constants.EXPORT_TASK_ENUM.RESOURCE_TYPE.FANS,
                JSONUtil.toJsonStr(activityAwardDTO)
        );
//        // 发送mq
//        mqSender.send(ExportExcelMQ.build(exportTaskId));
    }

    /**
     * 查询 报表名称：“越减越便宜-商户版”活动发展通报
     * @param activityAwardDTO
     * @return
     */
    public StatActe017MchVO getStatMchV(ActivityAwardDTO activityAwardDTO) {
        List<StatActe017NumVO> items = statActe017NumMapper.getStatMchV(activityAwardDTO);
        // 求和汇总
        setSum(items);
        return setStatActe017MchVO(items);
    }

    /**
     * 将数组转化为新组成的vo对象
     * @param items
     * @return
     */
    private StatActe017MchVO setStatActe017MchVO(List<StatActe017NumVO> items) {
        StatActe017MchVO statActe017MchVO = new StatActe017MchVO();
        // 16个区县数据
        statActe017MchVO.setList(items);
        // 设置统计性文本详情
        statActe017MchVO.setTitleDetail(this.setTitleDetail(items));
        // 设置统计性文本排名
        statActe017MchVO.setRankList(this.setRankList(items));
        return statActe017MchVO;
    }

    /**
     * 设置统计性文本，具体的内如如下：
     * 文字叙述：(统计性文本)
     *     截至XXXX年XX月XX日，全市活动季度累计开展X（共开展几期活动）场，
     *     累计参与X（活动参与人数）人，客户激发覆盖率X（客户激发人数/活动参与人数）%，
     *     客户转介X（B1券激发总人次）人次，实名认证X（B2福分激发总人次）人次，
     *     本人新开户X（B3券激发总人次）人次，客户新增存款10万元以上X（C券激发总人次）万元，
     *     办理手机银行/绑卡X（D实物激发总人次）人次。
     *     活动参与人数前三位的单位：第一、第二、第三（活动参与点均排名“前三的区县）。
     *     活动参与人数后三位的单位：倒一、倒二、倒三（活动参与点均排名“后三的区县）。
     *     （除A券外）客户激发人数前三单位：第一、第二、第三（“客户激发点均排名“前三的区县）。
     *     （除A券外）客户激发人数后三单位：倒一、倒二、倒三（客户激发点均排名“后三的区县）。
     *     综合得分前三的单位：第一、第二、第三（综合排名“前三的区县）。
     *     综合得分后三的单位：倒一、倒二、倒三（综合排名“后三的区县）。
     * @param items
     */
    private String setTitleDetail(List<StatActe017NumVO> items) {
        StatActe017NumVO sum = items.get(items.size() - 1); // 汇总
        // 共开展几期活动
        long count = ObjectUtil.isEmpty(acte017Service.getCount()) ? 0 : acte017Service.getCount();
        // 累计参与X 
        Integer joinManNum = sum.getJoinManNum();
        // 客户激发覆盖率 客户激发人数/活动参与人数
        String activeRate1 = sum.getPromoteManCoverage();
        //客户转介X B1券激发总人次
        Integer totalB1ActiveNum = sum.getTotalB1ActiveNum();
        // 实名认证X（B2福分激发总人次）
        Integer totalB2GetNum = sum.getTotalB2GetNum();
        //本人新开户X B3券激发总人次
        Integer totalB3ActiveNum = sum.getTotalB3ActiveNum();
        // 客户新增存款10万元以上X C券激发总人次
        Integer totalCActiveNum = sum.getTotalCActiveNum();
        // 办理手机银行/绑卡X  D实物激发总人次
        Integer totalDActiveNum = sum.getTotalDActiveNum();

        return "截至" + DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN) + "，全市活动季度累计开展"+ count +"（共开展几期活动）场，累计参与" + joinManNum + "（活动参与人数）人，客户激发覆盖率" + activeRate1 + "（客户激发人数/活动参与人数），" +
                "客户转介" + totalB1ActiveNum + "（B1券激发总人次）人次，实名认证" + totalB2GetNum + "（B2福分激发总人次）人次，本人新开户" + totalB3ActiveNum + "（B3券激发总人次）人次，客户新增存款10万元以上" + totalCActiveNum + "（C券激发总人次）万元，" +
                "办理手机银行/绑卡" + totalDActiveNum + "（D实物激发总人次）人次。";
    }

    private List<String> setRankList(List<StatActe017NumVO> items) {
        // 活动参与人数前三位的单位 第一、第二、第三
        String top3JoinManNum = items.subList(0, items.size() - 1).stream()
                .sorted((p1, p2) -> Integer.compare(p2.getJoinManNum(), p1.getJoinManNum()))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        // 活动参与人数后三位的单位 第一、第二、第三
        String last3JoinManNum = items.subList(0, items.size() - 1).stream()
                .sorted(Comparator.comparing(StatActe017NumVO::getJoinManNum))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        // （除A券外）客户激发人数前三单位 第一、第二、第三（“客户激发点均排名“前三的区县）。
        String top3PromoteManNum = items.subList(0, items.size() - 1).stream()
                .sorted((p1, p2) -> Integer.compare(p2.getPromoteManNum(), p1.getPromoteManNum()))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        // （除A券外）客户激发人数后三单位：倒一、倒二、倒三（客户激发点均排名“后三的区县）。
        String last3PromoteManNum = items.subList(0, items.size() - 1).stream()
                .sorted(Comparator.comparing(StatActe017NumVO::getPromoteManNum))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        // 综合得分前三的单位：第一、第二、第三（综合排名“前三的区县）。
        String top3TotalGrade = items.subList(0, items.size() - 1).stream()
                .sorted((p1, p2) -> Double.compare(p2.getTotalGrade(), p1.getTotalGrade()))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        // 综合得分后三的单位：倒一、倒二、倒三（综合排名“后三的区县）。
        String last3TotalGrade = items.subList(0, items.size() - 1).stream()
                .sorted(Comparator.comparing(StatActe017NumVO::getTotalGrade))
                .limit(3)
                .map(StatActe017NumVO::getAgentName3)
                .collect(Collectors.joining("、"));
        List<String> rankList = new ArrayList<>();
        rankList.add("活动参与人数前三位的单位：" + top3JoinManNum);
        rankList.add("活动参与人数后三位的单位：" + last3JoinManNum);
        rankList.add("（除A券外）客户激发人数前三单位：" + top3PromoteManNum);
        rankList.add("（除A券外）客户激发人数后三单位：" + last3PromoteManNum);
        rankList.add("综合得分前三的单位：" + top3TotalGrade);
        rankList.add("综合得分后三的单位：" + last3TotalGrade);
        return rankList;
    }

    /**
     * 导出 报表名称：“越减越便宜-商户版”活动发展通报
     * @param activityAwardDTO
     * @return
     */
    public void exportStatMchV(ActivityAwardDTO activityAwardDTO) {
        String fileName = "“越减越便宜-商户版”活动发展通报--截至" + DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN);
        // 添加导出任务记录
        this.sysExportTaskService.addExportTask(
                GzUserDetails.getCurrentUserDetails().getSysUser(),
                fileName,
                Constants.EXPORT_TASK_ENUM.REQUEST_CODE.MCH_DETAIL,
                Constants.EXPORT_TASK_ENUM.RESOURCE_TYPE.FANS,
                JSONUtil.toJsonStr(activityAwardDTO)
        );
    }

    /**
     * 求和汇总
     *
     * @param items
     */
    private void setSum(List<StatActe017NumVO> items) {
        StatActe017NumVO item = new StatActe017NumVO();
        item.setAgentName3("合计");
        // 统计网点数目
        item.setNextAgentNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getNextAgentNum)
                        .sum()
        );
        // 求和活动参与人数
        item.setJoinManNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getJoinManNum)
                        .sum()
        );
        // 求和活动参与人次
        item.setJoinManTime(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getJoinManTime)
                        .sum()
        );
        // 活动参与点均 活动参与总人次/网点总数
        item.setJoinManTimeAverage(
                getTotalAvg(item.getJoinManTime(), item.getNextAgentNum())
        );
        // 客户激发人数
        item.setPromoteManNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getPromoteManNum)
                        .sum()
        );
        // 客户激发点均 客户激发总人数/网点总数
        item.setPromoteManNumAverage(
                getTotalAvg(item.getPromoteManNum(), item.getNextAgentNum())
        );
        // 客户激发覆盖率 客户激发总人数/活动参与总人数
        item.setPromoteManCoverage(
                getTotalAvg(item.getPromoteManNum(), item.getJoinManNum()) + "%"
        );
        // 求和B1券激发人次
        item.setTotalB1ActiveNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getTotalB1ActiveNum)
                        .sum()
        );
        // B1券点均 B1券激发总人次/网点总数
        item.setTotalB1ActiveNumAverage(
                getTotalAvg(item.getTotalB1ActiveNum(), item.getNextAgentNum())
        );
        // B1券激活率 B1券激发总人次/B1券发放总人次
        item.setTotalB1ActiveRate(
                getTotalAvg(
                        item.getTotalB1ActiveNum(),
                        items.parallelStream()
                                .mapToInt(StatActe017NumVO::getTotalB1SendNum)
                                .sum()
                ) + "%"
        );
        // B2福分激发人次 求和B2福分激发人次
        item.setTotalB2GetNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getTotalB2GetNum)
                        .sum()
        );
        // B2福分点均 B2福分激发总人次/网点总数
        item.setTotalB2GetNumAverage(
                getTotalAvg(item.getTotalB2GetNum(), item.getNextAgentNum())
        );
        // B3券激发人次 求和B3券激发人次
        item.setTotalB3ActiveNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getTotalB3ActiveNum)
                        .sum()
        );
        // B3券点均 B3券总激发人次/网点总数
        item.setTotalB3ActiveNumAverage(
                getTotalAvg(item.getTotalB3ActiveNum(), item.getNextAgentNum())
        );
        // B3券激活率 B3券激发总人次/B3券发放总人次
        item.setTotalB3ActiveRate(
                getTotalAvg(
                        item.getTotalB3ActiveNum(),
                        items.parallelStream()
                                .mapToInt(StatActe017NumVO::getTotalB3SendNum)
                                .sum()
                ) + "%"
        );
        // C券激发人次 求和C券激发人次
        item.setTotalCActiveNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getTotalCActiveNum)
                        .sum()
        );
        // C券点均 C券激发总人次/网点总数
        item.setTotalCActiveNumAverage(
                getTotalAvg(item.getTotalCActiveNum(), item.getNextAgentNum())
        );
        //C券激活率 C券激发总人次/C券发放总人次
        item.setTotalCActiveRate(
                getTotalAvg(
                        item.getTotalCActiveNum(),
                        items.parallelStream()
                                .mapToInt(StatActe017NumVO::getTotalCSendNum)
                                .sum()
                ) + "%"
        );
        // D实物激发人次 求和D实物激发人次
        item.setTotalDActiveNum(
                items.parallelStream()
                        .mapToInt(StatActe017NumVO::getTotalDActiveNum)
                        .sum()
        );
        // D实物点均 D实物激发总人次/网点总数
        item.setTotalDActiveNumAverage(
                getTotalAvg(item.getTotalDActiveNum(), item.getNextAgentNum())
        );
        // D实物激活率 D实物激发总人次/D实物发放总人次
        item.setTotalDActiveRate(
                getTotalAvg(
                        item.getTotalDActiveNum(),
                        items.parallelStream()
                                .mapToInt(StatActe017NumVO::getTotalDSendNum)
                                .sum()
                ) + "%"
        );
        // 添加总计 item
        items.add(item);
    }

    /**
     * 计算均值
     * @param val1
     * @param val2
     * @return
     */
    private double getTotalAvg(int val1, int val2){
        if (val1 == 0 || val2 == 0){
            return 0.0;
        }
        return (double) val1 / val2;
    }
}
